/**
 * 
 */
package org.mhz.ootw.logging;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

/**
 * @author Mahan
 *
 * Logging interceptor class
 */
@Component
@Aspect
public class LoggingInterceptor
{    
    @Pointcut("execution(public * *(..))")
    private void anyPublicOperation() { }
    
    @Pointcut("within(org.mhz.ootw.ui..*)")
    public void inUILayer() { }
    
    @Pointcut("within(org.mhz.ootw.service..*)")
    public void inServiceLayer() { }
    
    @Pointcut("within(org.mhz.ootw.dao..*)")
    public void inDataAccessLayer() { }
    
    /**
     * Log the time taken for a method
     *
     * @param aProceedingJoinPoint - The proceeding join point
     * @throws Throwable
     */
    @Around("anyPublicOperation() && @annotation(org.mhz.ootw.annotation.LogTimeTaken)")
    public Object logTimeTaken(final ProceedingJoinPoint aProceedingJoinPoint) throws Throwable
    {    	
        final String nameOfClass = aProceedingJoinPoint.getTarget().toString();
        final Logger logger = LoggerFactory.getLogger(nameOfClass);
        
        final String shortDescr = aProceedingJoinPoint.toShortString();
        final String nameOfMethod = aProceedingJoinPoint.getSignature().getName();
        
        final StopWatch sw = new StopWatch();
        
        // Start the stopwatch
        sw.start(nameOfMethod);

        // Invoke method
        final Object retVal = aProceedingJoinPoint.proceed();
        
        // Stop the stopwatch
        sw.stop();
        
        logger.info("{} took {}ms", new Object[] {shortDescr, sw.getTotalTimeMillis()});
        
        return retVal;
    }
    
    /**
     * Log around a method
     *
     * @param aProceedingJoinPoint - The proceeding join point
     * @throws Throwable
     */
    /*@Around("anyPublicOperation()")
    public void logAround(final ProceedingJoinPoint aProceedingJoinPoint) throws Throwable
    {
        if (mLoggingEnabled)
        {
            final String nameOfClass = aProceedingJoinPoint.getTarget().toString();
            final Logger logger = LoggerFactory.getLogger(nameOfClass);
            
            final String shortDescr = aProceedingJoinPoint.toShortString();
            final String nameOfMethod = aProceedingJoinPoint.getSignature().getName();
            
            final StopWatch sw = new StopWatch();
            
            // Start the stopwatch
            sw.start(nameOfMethod);
            
            logger.info(">> {}", shortDescr);

            // Invoke method
            aProceedingJoinPoint.proceed();

            // Stop the stopwatch
            sw.stop();
            
            logger.info("<< {}. Time taken: {}ms", new Object[] {shortDescr, sw.getTotalTimeMillis()});
        }
        else
        {
            aProceedingJoinPoint.proceed();
        }
    }*/    
}
